package mixlog

import (
	"bytes"
	"fmt"
	"os"
	"strings"
	"text/template"
)

const (
	// 日志条目格式化成字符串的常用模板
	FormatLongFileName          = "{{.Lvl}} - {{.Time}} - {{.LongFileName}}({{.Line}}) - {{.Message}}"
	FormatShortFileName         = "{{.Lvl}} - {{.Time}} - {{.ShortFilename}}({{.Line}}) - {{.Message}}"
	FormatFuncNameLongFileName  = "{{.Lvl}} - {{.Time}} - {{.FuncName}} - {{.LongFileName}}({{.Line}}) - {{.Message}}"
	FormatFuncNameShortFileName = "{{.Lvl}} - {{.Time}} - {{.FuncName}} - {{.ShortFilename}}({{.Line}}) - {{.Message}}"

	// defaultTimeLayout 默认的时间格式布局
	defaultTimeLayout = "2006-01-02T15:04:05.000-07:00"
)

// Formatter 日志条目格式化
type formatter struct {
	// Tpl 字符串模板对象
	Tpl *template.Template

	// TimeLayout 时间格式化模板
	TimeLayout string

	// needRuntimeCaller 模板中包含了需要 `runtime.Caller` 获取的信息
	// {{.FuncName}} {{.LongFileName}} {{.ShortFilename}} {{.Line}}
	needRuntimeCaller bool
}

// logFormat 将日志条目格式化成字符串
func (f *formatter) logFormat(entry entry) string {
	entry.Time = entry.t.Format(f.TimeLayout)

	buf := new(bytes.Buffer)
	if err := f.Tpl.Execute(buf, entry); err != nil {
		_, _ = fmt.Fprintln(os.Stderr, err.Error())
		return ""
	}
	return buf.String()
}

// NewFormatter 创建一个格式化器
func NewFormatter(format, timeLayout string) (*formatter, error) {
	if timeLayout == "" {
		timeLayout = defaultTimeLayout
	}
	tpl, err := template.New("").Parse(format)
	if err != nil {
		return nil, err
	}

	f := &formatter{Tpl: tpl, TimeLayout: timeLayout}
	for _, keyStr := range []string{"{{.FuncName}}", "{{.LongFileName}}", "{{.ShortFilename}}", "{{.Line}}"} {
		if strings.Contains(format, keyStr) {
			f.needRuntimeCaller = true
			break
		}
	}

	return f, nil
}

func MustNewFormatter(format, timeLayout string) *formatter {
	f, err := NewFormatter(format, timeLayout)
	if err != nil {
		panic(err)
	}
	return f
}
